Skip to content
View Article Network

Implementing GDPR in ASP.NET Core

General Data Protection Regulation

When browsing the web, if you see a message like "This website uses cookies, do you accept?", this stems from the "General Data Protection Regulation (GDPR)" passed by the European Union on April 27, 2016, which became enforceable on May 25, 2018. Its purpose is to regulate the data and privacy of EU individuals. For the full content, please refer to Wiki GDPR.

In addition to the EU's GDPR, the U.S. state of California has similar regulations, such as the California Consumer Privacy Act (CCPA) and the California Online Privacy Protection Act (CalOPPA).

Implementation Methods

  • Create a Privacy Policy page: If you use Visual Studio to create a .NET Core 2.1 or later Web project, you will find an additional "Privacy" page. This is used to display the website's Privacy Policy. For an example of a privacy policy, you can refer to the Chinese Privacy Policy Template for Websites. According to the author, this is a version adjusted based on the "Government Website Layout and Content Management Guidelines." However, I could not find the original template. For commercial use, it is best to verify whether the content complies with regulations like GDPR.

  • Displaying cookie-related messages on the webpage:

    • Provide a link to the "Privacy and Cookie Policy" page.
    • Ask for consent to the policy. Approaches generally fall into the following categories:
      • No explicit prompt: Simply inform the user that continuing to use the site implies consent to the privacy policy, and provide a "Close" button.
      • Inform the user that continuing to use the site implies consent, and provide both "Accept" and "Close" buttons.
      • Do not assume consent by continued browsing, and provide both "Accept" and "Close" buttons.
      • Categorize the types of cookies used on the site, allowing users to consent only to necessary cookies. "Stack Overflow" is an example of this. If you are interested, you can browse in incognito mode to see that they provide a "Customize settings" button, allowing you to adjust the types of cookies you allow.
    • Handling the dismissal of the prompt message:
      • Dismiss: Only hides the message temporarily; it will reappear when the page is reloaded.
      • Accept: Write a flag to a cookie. When this cookie exists, the prompt message is no longer displayed, and subsequent actions can be taken based on this flag to decide whether to write other cookies.
  • Methods for not writing cookies until the user consents: Some sites inform users that "continuing to use this site implies consent to the privacy policy" because they do not want to handle the logic of stopping cookie writes. Therefore, they default to user consent and explain in the privacy policy that users can adjust browser settings to block cookies. Of course, reasonably speaking, non-essential cookies should be stopped until the user provides consent.

    Implementing this part is not difficult. Instead of using the native framework API, you can write a Facade to encapsulate it. Only call the native API when the user's consent cookie is present.

    For MVC, the simplest approach is to write a BasicController that other controllers inherit from, using its AddCookie method to add a Response Cookie. An example is as follows:

csharp
public abstract BasicController {
    public void AddCookie(HttpCookie cookie) {
        // Please adjust the Cookie Name and Value according to your actual situation
        if (Request.Cookies["UseCookies"] == "yes") {
            Response.Cookies.Add(cookie);
        }
    }
}

Implementation using ASP.NET Core

The .NET Core 2.1 project template already includes a GDPR implementation (excluding the privacy policy content). However, in subsequent versions (I haven't tested which specific version, but MSDN states it is provided in templates after 2.2), the page implementation was removed, leaving only the API. Nevertheless, a GDPR implementation example is provided on MSDN. Basically, besides needing to adjust the HTML to match your UI framework and updating the text according to your policy (you also need to adjust it if you don't use jQuery, as the code uses native DOM APIs but still includes $.ready()), this section focuses on explaining the official example.

Below, I use "Consent" to represent the cookie for "Allow Cookie Usage Settings."

Program.cs

csharp
builder.Services.Configure<CookiePolicyOptions>(options => {
    // If set to true, "Consent" is required to set non-essential cookies
    options.CheckConsentNeeded = context => true;

    options.MinimumSameSitePolicy = SameSiteMode.None;
});

// ...other code...

app.UseCookiePolicy(); // Cookie-related middleware is configured here

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

_CookieConsentPartial.cshtml

  • The default Injection Instance type for ITrackingConsentFeature is ResponseCookiesWrapper (the specific DI behavior occurs at app.UseCookiePolicy()).
  • The value of consentFeature?.CanTrack is true if CookiePolicyOptions.CheckConsentNeeded(HttpContext) is true and the "Consent" cookie exists. In other words, if CheckConsentNeeded = context => false is set in Program.cs, the reminder will not be displayed.
  • consentFeature?.CreateConsentCookie() is used to create the text for the "Consent" cookie. The content is roughly .AspNet.Consent=yes; expires={date}; path=/; secure. The "Consent" cookie is not actually created here, but rather when document.cookie = button.dataset.cookieString; is executed.
html
@using Microsoft.AspNetCore.Http.Features

@{
    var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
    var showBanner = !consentFeature?.CanTrack ?? false;
    var cookieString = consentFeature?.CreateConsentCookie();
}

@if (showBanner) {
    <div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
        Use this space to summarize your privacy and cookie use policy. <a asp-page="/Privacy">Learn More</a>.
        <button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
            <span aria-hidden="true">Accept</span>
        </button>
    </div>
    <script>
        (function () {
            var button = document.querySelector("#cookieConsent button[data-cookie-string]");
            button.addEventListener("click", function (event) {
                document.cookie = button.dataset.cookieString;
            }, false);
        })();
    </script>
}

Essential Cookies

Some cookies are non-essential, such as those for preferences that optimize the user experience. However, some cookies affect the normal operation of the website. If you want the site to function normally even if the user has not consented to cookie usage (the prompt message should ideally explain this situation), such cookies should be set with IsEssential = true.

csharp
Response.Cookies.Append("name", "value", new CookieOptions {
   IsEssential = true // Indicates that this cookie is essential
});

Change Log

  • 2022-10-27 Initial document creation.